package com.ithuameng.cosy.config;

import com.ithuameng.cosy.acceptor.WebsocketAcceptor;
import com.ithuameng.cosy.acceptor.config.WebsocketConfig;
import com.ithuameng.cosy.component.handler.annotation.CIMHandler;
import com.ithuameng.cosy.component.predicate.HandshakePredicate;
import com.ithuameng.cosy.config.properties.CIMWebsocketProperties;
import com.ithuameng.cosy.group.SessionGroup;
import com.ithuameng.cosy.group.TagSessionGroup;
import com.ithuameng.cosy.handler.CIMRequestHandler;
import com.ithuameng.cosy.model.SentBody;
import com.ithuameng.cosy.service.ISessionService;
import com.ithuameng.cosy.util.ClassUtils;
import io.netty.channel.Channel;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.event.ApplicationStartedEvent;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;

@EnableConfigurationProperties(CIMWebsocketProperties.class)
@Configuration
public class CIMConfig implements CIMRequestHandler, ApplicationListener<ApplicationStartedEvent> {

    @Resource
    private ApplicationContext applicationContext;

    @Resource
    private ISessionService sessionService;

    private final HashMap<String, CIMRequestHandler> handlerMap = new HashMap<>();

    @Bean
    public SessionGroup sessionGroup() {
        return new SessionGroup();
    }

    @Bean
    public TagSessionGroup tagSessionGroup() {
        return new TagSessionGroup();
    }

    @Bean(destroyMethod = "destroy", initMethod = "bind")
    @ConditionalOnProperty(name = {"cim.websocket.enable"}, matchIfMissing = true)
    public WebsocketAcceptor websocketAcceptor(CIMWebsocketProperties properties, HandshakePredicate handshakePredicate) {
        WebsocketConfig config = new WebsocketConfig();
        config.setHandshakePredicate(handshakePredicate);
        config.setPath(properties.getPath());
        config.setPort(properties.getPort());
        config.setProtocol(properties.getProtocol());
        config.setOuterRequestHandler(this);
        config.setEnable(properties.isEnable());
        config.setSslEnable(properties.isSslEnable());
        config.setSslType(properties.getSslType());
        config.setSslPath(ClassUtils.getDefaultClassLoader().getResource(properties.getSslFileName()).getPath());
        config.setSslPassword(properties.getSslPassword());
        return new WebsocketAcceptor(config);
    }

    @Override
    public void process(Channel channel, SentBody body) {
        CIMRequestHandler handler = handlerMap.get(body.getKey());
        if (handler == null) {
            return;
        }
        handler.process(channel, body);
    }

    /**
     * springboot启动完成之后再启动cim服务的，避免服务正在重启时，客户端会立即开始连接导致意外异常发生.
     */
    @Override
    public void onApplicationEvent(ApplicationStartedEvent applicationStartedEvent) {
        // 获取CIMRequestHandler的所有实现类
        Map<String, CIMRequestHandler> beans = applicationContext.getBeansOfType(CIMRequestHandler.class);
        for (Map.Entry<String, CIMRequestHandler> entry : beans.entrySet()) {
            // 将实现类上有CIMHandler注释的Map
            CIMRequestHandler handler = entry.getValue();
            CIMHandler annotation = handler.getClass().getAnnotation(CIMHandler.class);
            if (annotation != null) {
                handlerMap.put(annotation.key(), handler);
            }
        }
        sessionService.deleteAll();
    }
}